/////////////////////////////////////////////////////////////////////////////
// Name of module : pixel_addr_decoder                                     //
// Func           : 根据port、scan等pixel在sdram的地址                    //
// Author         : heguangzu                                              //
// Simulator      :                                                        //
// Synthesizer    :                                                        //
// version 1.0    : made in Date: 2019.05.23                               //
/////////////////////////////////////////////////////////////////////////////

module pixel_addr_decoder(
    input   wire            I_sclk      ,
    input   wire            I_rst_n     ,
    
    input   wire            I_req       ,
    output  wire            O_req_end   ,
    
    input   wire    [5:0]   I_port_id   ,
    input   wire    [5:0]   I_scan_id   ,
    input   wire    [1:0]   I_frame_sel ,
    
    input   wire    [10:0]  I_line_max_pixel   ,      //一扫的像素---4的倍数。 从1 开始计数
    input   wire    [5:0]   I_cfg_port_max     ,      //最大port_id 从0计数
    input   wire    [5:0]   I_cfg_scan_max     ,      //最大scan_id 从0 计数
    input   wire    [1:0]   I_cfg_box_dir      ,      //箱体方向
    input   wire    [3:0]   I_cfg_sector_count ,      //多开数量
    input   wire    [10:0]  I_cfg_sector_width ,      //分区宽度
    input   wire    [10:0]  I_cfg_sector_height,      //区域的高度
    input   wire    [7:0]   I_cfg_port_height  ,      //port的高度
    input   wire    [3:0]   I_cfg_block_max    ,      //列模式下多开的数量
    
    input   wire    [10:0]  I_cfg_win_col_num  ,      // 带载列数（宽度）
    input   wire    [10:0]  I_cfg_win_row_num  ,      // 带载行数（高度）
    
    output  wire    [20:0]  O_pixel_sdram_addr        , //像素地址
    output  wire    [9:0]   O_pixel_sdram_len         , //现在必需是4的倍数
    output  wire    [2:0]   O_pixel_sdram_req_cnt     , //读几行 从0开始计数 相当有几折
    output  wire    [20:0]  O_pixel_sdram_add         , //每行之间的地址差
    output  wire    [20:0]  O_pixel_sdram_col_add     , //按列读时，每64个列之间的地址差

    output  wire    [20:0]  O_adj_sdram_addr          , //校正地址
    output  wire    [9:0]   O_adj_sdram_len           , //现在必需是4的倍数
    output  wire    [2:0]   O_adj_sdram_req_cnt       , //读几行 从0开始计数 相当有几折
    output  wire    [20:0]  O_adj_sdram_add           , //每行之间的地址差
    output  wire    [20:0]  O_adj_sdram_col_add       , //按列读时，每64个列之间的地址差
    output  wire    [20:0]  O_adj_sdram_add1          ,//每种校正分量的地址差
    
    output  wire    [9:0]   O_gap_coe_addr_row        ,// 行坐标
    output  wire    [9:0]   O_gap_coe_addr_col        ,// 列坐标
    output  wire    [9:0]   O_gap_coe_len             ,//现在必需是4的倍数
    output  wire    [2:0]   O_gap_coe_req_cnt         ,//读几行 从0开始计数 相当有几折
    output  wire    [9:0]   O_gap_coe_add             //每行之间的地址差
);

// box direction
localparam [1:0]
    LANDSCAPE = 0, // 横向
    PORTRAIT0 = 1, // 纵向，第一个端口在左侧
    PORTRAIT1 = 2; // 纵向，第一个端口在右侧

//可上位机发
reg [13:0]  slip_count;
reg [12:0]  count_pixel_64; 
reg [5:0]   width_count; 
reg [5:0]   height_count;
reg [10:0]  width_int;   
reg [10:0]  height_int; 

reg [2:0]   scan_cnt;//折数
wire [6:0]scan_cnt_t;

reg [6:0]scan_max_1;
always  @(posedge I_sclk)begin
    width_count  <= width_int[10:6]; 
    height_count <= height_int[10:6];
    width_int    <= I_cfg_win_col_num + 63;   
    height_int   <= I_cfg_win_row_num + 63;  
    count_pixel_64<= width_count*height_count;
    scan_max_1      <= {1'd0,I_cfg_scan_max}+7'd1;
    scan_cnt        <= I_cfg_port_height / (I_cfg_scan_max+1);
end

wire    [5:0]   port_id_x;
wire    [5:0]   port_id_y; 
wire            done;
// reg            done;
reg     [5:0]   denom;       

reg landscape_mode;
//landscape_mode:  1 - 行控，0 - 列控
always@(posedge I_sclk)begin
    landscape_mode <= (I_cfg_box_dir == LANDSCAPE);
end

always@(posedge I_sclk )begin
    if(landscape_mode == 1)
        denom <= (I_cfg_port_max+1) /I_cfg_sector_count;
    else 
        denom <= (I_cfg_port_max+1) /(I_cfg_block_max+1);
end


serial_divider
#(
    .M(6),  //width of numerator
    .N(6),  //width of denominator
    .MODE(0)   //0 - unsigned, 1 - signed
)  por_id_x_y
(
    //system singal
    .I_sclk      (I_sclk        ),
    .I_rst_n     (I_rst_n       ),
    //divide
    .I_start     (I_req         ),
    .I_numer     (I_port_id     ),
    .I_denom     (denom         ),
    .O_done      (done          ),
    .O_quotient  (port_id_y     ),
    .O_remain    (port_id_x     )
);

// always@(posedge I_sclk or negedge I_rst_n)
    // if(!I_rst_n)
        // done<='d0;
    // else if(I_req)
        // done<='d1;
    // else 
        // done<='d0;

reg [9:0]w;
reg [9:0]h;
always@(posedge I_sclk )begin
    if(done)begin
        // w <= 0;
        // h <= I_port_id * I_cfg_port_height + I_scan_id;
            
        if(landscape_mode == 1)begin
            w <= port_id_y * I_cfg_sector_width;
            h <= port_id_x * I_cfg_port_height + I_scan_id;
        end
        else begin
            // w <= port_id_y * I_cfg_port_height + I_scan_id;
            // h <= port_id_x * I_cfg_sector_width;
            w <= port_id_x * I_cfg_port_height + I_scan_id;
            h <= port_id_y * I_cfg_sector_width;
        end
    
    end
end

reg [1:0]done_r;
always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        done_r <= 'd0;
    else 
        done_r <= {done_r[0] , done};
end
assign O_req_end = done_r[0];


reg     [20:0]  pixel_sdram_addr        ; //像素地址
reg     [9:0]   pixel_sdram_len         ; //现在必需是4的倍数
reg     [2:0]   pixel_sdram_req_cnt     ; //读几行 从0开始计数 相当有几折
reg     [20:0]  pixel_sdram_add         ; //每行之间的地址差
reg     [20:0]  pixel_sdram_col_add     ;
assign O_pixel_sdram_addr      =    pixel_sdram_addr      ; //像素地址
assign O_pixel_sdram_len       =    pixel_sdram_len       ; //现在必需是4的倍数
assign O_pixel_sdram_req_cnt   =    pixel_sdram_req_cnt   ; //读几行 从0开始计数 相当有几折
assign O_pixel_sdram_add       =    pixel_sdram_add       ; //每行之间的地址差
assign O_pixel_sdram_col_add   =    pixel_sdram_col_add      ; //每行之间的地址差

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n) begin
        pixel_sdram_addr  <= 'd0;
        pixel_sdram_len   <= 'd0;
        pixel_sdram_req_cnt<= 'd0;
        pixel_sdram_add   <= 'd0;
        pixel_sdram_col_add  <= 'd0;
    end
    else if(done_r[0])begin
        pixel_sdram_addr[1:0]     <= w[1:0];
        pixel_sdram_addr[7:2]     <= h[5:0];
        pixel_sdram_addr[11:8]    <= w[5:2];
        pixel_sdram_addr[17:12]   <= h[9:6]*width_count;
        pixel_sdram_addr[18]      <= I_frame_sel[0];
        pixel_sdram_addr[20:19]   <= 'd0;
    
        pixel_sdram_len           <= I_cfg_sector_width;
        if(scan_cnt!=0)
            pixel_sdram_req_cnt       <= scan_cnt-1;
        else 
            pixel_sdram_req_cnt       <= 0;
        // pixel_sdram_req_cnt       <= 0;
        
        if(landscape_mode == 1)begin
            pixel_sdram_add[1:0]      <= 'd0;
            pixel_sdram_add[7:2]      <= scan_max_1[5:0];
            pixel_sdram_add[11:8]     <= 'd0;
            pixel_sdram_add[17:12]    <= scan_max_1[6]?width_count:'d0;
            pixel_sdram_add[18]       <= 'd0;
            pixel_sdram_add[20:19]    <= 'd0;
        end
        else begin
            pixel_sdram_add[1:0]      <= scan_max_1[1:0];
            pixel_sdram_add[7:2]      <= 'd0;
            pixel_sdram_add[11:8]     <= scan_max_1[5:2];
            pixel_sdram_add[17:12]    <= scan_max_1[6];
            pixel_sdram_add[18]       <= 'd0;
            pixel_sdram_add[20:19]    <= 'd0;
        end
        
        pixel_sdram_col_add[17:12] <= width_count;
    end

end


reg     [20:0]  adj_sdram_addr       ;
reg     [9:0]   adj_sdram_len        ;
reg     [2:0]   adj_sdram_req_cnt    ;
reg     [20:0]  adj_sdram_add        ;
reg     [20:0]  adj_sdram_add1       ;
reg     [20:0]  adj_sdram_col_add    ;

assign  O_adj_sdram_addr     =  adj_sdram_addr   ;
assign  O_adj_sdram_len      =  adj_sdram_len    ;
assign  O_adj_sdram_req_cnt  =  adj_sdram_req_cnt;
assign  O_adj_sdram_add      =  adj_sdram_add    ;
assign  O_adj_sdram_add1     =  adj_sdram_add1   ;
assign  O_adj_sdram_col_add  =  adj_sdram_col_add;


always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n) begin
        adj_sdram_addr    <= 'd0;
        adj_sdram_len     <= 'd0;
        adj_sdram_req_cnt <= 'd0;
        adj_sdram_add     <= 'd0;
        adj_sdram_add1    <= 'd0;
        adj_sdram_col_add <= 'd0;
    end
    else if(done_r[0])begin
        adj_sdram_addr[1:0]     <= w[1:0];
        adj_sdram_addr[7:2]     <= h[5:0];
        adj_sdram_addr[11:8]    <= w[5:2];
        adj_sdram_addr[17:12]   <= h[9:6]*width_count;
        adj_sdram_addr[18]      <= I_frame_sel[0];
        adj_sdram_addr[20:19]   <= 'd3;
    
        adj_sdram_len           <= I_cfg_sector_width;
        if(scan_cnt!=0)
            adj_sdram_req_cnt       <= scan_cnt-1;
        else 
            adj_sdram_req_cnt       <= 0;
        // adj_sdram_req_cnt       <= 0;
        
         if(landscape_mode == 1)begin
            adj_sdram_add[1:0]      <= 'd0;
            adj_sdram_add[7:2]      <= scan_max_1[5:0];
            adj_sdram_add[11:8]     <= 'd0;
            adj_sdram_add[17:12]    <= scan_max_1[6]?width_count:'d0;
            adj_sdram_add[18]       <= 'd0;
            adj_sdram_add[20:19]    <= 'd0;
        end
        else begin
            adj_sdram_add[1:0]      <= scan_max_1[1:0];
            adj_sdram_add[7:2]      <= 'd0;
            adj_sdram_add[11:8]     <= scan_max_1[5:2];
            adj_sdram_add[17:12]    <= scan_max_1[6];
            adj_sdram_add[18]       <= 'd0;
            adj_sdram_add[20:19]    <= 'd0;
        end
        
        adj_sdram_add1[1:0]      <= 'd0;
        adj_sdram_add1[7:2]      <= 'd0;
        adj_sdram_add1[11:8]     <= 'd0;
        adj_sdram_add1[17:12]    <= count_pixel_64[5:0];
        adj_sdram_add1[18]       <= 'd0;
        adj_sdram_add1[20:19]    <= 'd0;
        
        adj_sdram_col_add[17:12] <= width_count;
    end

end


reg     [9:0]   gap_coe_addr_row        ;// 行坐标
reg     [9:0]   gap_coe_addr_col        ;// 列坐标
reg     [9:0]   gap_coe_len             ;//现在必需是4的倍数
reg     [2:0]   gap_coe_req_cnt         ;//读几行 从0开始计数 相当有几折
reg     [9:0]   gap_coe_add             ;

assign  O_gap_coe_addr_row  =   gap_coe_addr_row  ;
assign  O_gap_coe_addr_col  =   gap_coe_addr_col  ;
assign  O_gap_coe_len       =   gap_coe_len       ;
assign  O_gap_coe_req_cnt   =   gap_coe_req_cnt   ;
assign  O_gap_coe_add       =   gap_coe_add       ;

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n) begin
        gap_coe_addr_row    <= 'd0;
        gap_coe_addr_col    <= 'd0;
        gap_coe_len         <= 'd0;
        gap_coe_req_cnt     <= 'd0;
        gap_coe_add         <= 'd0;
    end
    else if(done_r[0])begin
        gap_coe_addr_row            <= h[9:0];
        gap_coe_addr_col            <= w[9:0];
        gap_coe_len                 <= I_cfg_sector_width;
        if(scan_cnt!= 0)
            gap_coe_req_cnt             <= scan_cnt-1;
        else 
            gap_coe_req_cnt             <= 0;
        // gap_coe_req_cnt             <= 0;
        gap_coe_add                 <= scan_max_1;
    end

end



endmodule
// vim:set ts=4 sw=4 et fenc=utf-8 fdm=marker: